﻿using Orleans;
using Orleans.Concurrency;
using Orleans.Runtime.Services;
using Orleans.Services;

namespace orleans_demo.Services
{
    public interface IDataServiceGrain : IGrainService
    {
        Task MyMethod();
    }
    /// <summary>
    /// Grain 服务是远程可访问的分区服务，用于支持功能 grain。 grain 服务的每个实例都负责一些 grain 集，
    /// 这些 grain 可以获取对 grain 服务的引用，该服务当前负责通过使用 GrainServiceClient 来维护它们。

      ///grain 服务的存在是为了支持应围绕 Orleans 群集分散维护 grain 的责任的情况。 
      ///例如，Orleans 提醒是使用 grain 服务实现的：每个 silo 负责处理一部分 grain 的提醒操作
      ///，并在提醒触发时通知这些 grain。
    /// </summary>
    [Reentrant]
    public class DataServiceGrain : GrainService, IDataServiceGrain
    {
        readonly IGrainFactory _grainFactory;
        public DataServiceGrain(
        IServiceProvider services,
            GrainId id,
            Silo silo,
            ILoggerFactory loggerFactory,
            IGrainFactory grainFactory)
            : base(id, silo, loggerFactory)
        {
            _grainFactory = grainFactory;
        }

        public override Task Init(IServiceProvider serviceProvider) =>
            base.Init(serviceProvider);

        public override Task Start() => base.Start();

        public override Task Stop() => base.Stop();

        public async Task MyMethod()
        {
            var userGrain = _grainFactory.GetGrain<IUserIndexGrain>("0");
            var list = await userGrain.GetAllUser();
            // TODO: custom logic here.
            await Task.CompletedTask;
        }
    }


    public interface IDataServiceClient : IGrainServiceClient<IDataServiceGrain>, IDataServiceGrain
    {
    }

    public class DataServiceClient : GrainServiceClient<IDataServiceGrain>, IDataServiceClient
    {
        public DataServiceClient(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }

        // For convenience when implementing methods, you can define a property which gets the IDataService
        // corresponding to the grain which is calling the DataServiceClient.
        private IDataServiceGrain GrainService => GetGrainService(CurrentGrainReference.GrainId);

        public Task MyMethod() => GrainService.MyMethod();
    }
}
